package org.blankie.model.fs;


import java.io.File;
import java.io.FileFilter;
import java.util.Collection;

import org.blankie.lang.Validate;
import org.blankie.model.DriverOperations;

class BlkFSOperations implements DriverOperations<BlkFSPath, BlkFileSystem, BlkFolder, BlkFile> {

    private static final long serialVersionUID = 0L;

    public static boolean isParent(File parent, File child) {
        return ((parent != null) && (child != null) && (parent.equals(child) || isParent(parent, child.getParentFile())));
    }
    
    private final FileFilter fileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isFile();
        }
    };

    private final FileFilter directoryFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isDirectory();
        }
    };
    
    BlkFSOperations() {
        super();
    }

    @Override
    public void loadLeaves(BlkFolder folder, Collection<BlkFSPath> into) {
        File[] files = folder.getId().getFile().listFiles(fileFilter);

        for (File file : files) {
            into.add(new BlkFSPath(file));
        }
    }
    
    void loadRoots(Collection<BlkFSPath> into) {
        File[] roots = File.listRoots();

        for (File file : roots) {
            into.add(new BlkFSPath(file));
        }
    }

    @Override
    public void loadNodes(BlkFolder folder, Collection<BlkFSPath> into) {
        File[] folders = folder.getId().getFile().listFiles(directoryFilter);

        for (File aFolder : folders) {
            into.add(new BlkFSPath(aFolder));
        }
    }

    // TODO implement a file system system.
    @Override
    public BlkFSPath findOrganization(BlkFSPath path) {
        File root = null;
        
        for (File aRoot : File.listRoots()) {
            if (isParent(aRoot, path.getFile())) {
                root = aRoot;
                break;
            }
        }
        
        Validate.notNull(root);
        return new BlkFSPath(root);
    }

    @Override
    public BlkFSPath findParent(BlkFSPath path) {
        return new BlkFSPath(path.getFile().getParentFile());
    }

    @Override
    public boolean testLeaves(BlkFolder folder) {
        return folder.getId().getFile().listFiles(fileFilter).length > 0;
    }

    @Override
    public boolean testNodes(BlkFolder folder) {
        return folder.getId().getFile().listFiles(directoryFilter).length > 0;
    }

    @Override
    public boolean testRoot(BlkFolder folder) {
        return folder.getId().getFile().getParentFile() == null;
    }

    @Override
    public BlkFSPath findRoot(BlkFSPath path) {
        return findOrganization(path);
    }
    
}
